package Parser;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Lexer {
	private BufferedReader reader;
	private File inputFile;
	private boolean intnumBit = false;
	private boolean idBit = false;
	private boolean beginBit = false;
	private boolean endBit = false;
	private boolean printBit = false;
	private boolean readBit = false;
	String inputString;
	private boolean leftBit = false;
	private boolean rightBit = false;
	private boolean semiBit = false;
	private boolean assignBit = false;
	private boolean commaBit = false;
	private boolean plusBit = false;
	private boolean minusBit = false;
	private boolean multiplyBit = false;
	private boolean moduloBit = false;
	private String[] tokens;

	final static private int MAX_ID_LENGTH = 10;
	final static private String STRING_ALPHA = "[a-zA-Z]";
	final static private String STRING_ALPHA_NUMERIC = "[a-zA-Z0-9]";
	final static private String STRING_ID = String.format("(%s|_%s)(_?%s)*", STRING_ALPHA, STRING_ALPHA_NUMERIC, STRING_ALPHA_NUMERIC);

	final static private Pattern PATTERNID = Pattern.compile(STRING_ID);
	final static private Pattern PATTERNNUM = Pattern.compile("[1-9][0-9]*|0");

	/**
	 * Constructor for Lexer. 
	 * 
	 * @param tokenMap
	 * @param inputFile
	 */
	public Lexer(File inputFile, String[] tokenList) {
		try {
			for (String e: tokenList) {
				if (e.equals("BEGIN")) beginBit = true;
				if (e.equals("END")) endBit = true;
				if (e.equals("PRINT")) printBit = true;
				if (e.equals("LEFTPAR")) leftBit = true;
				if (e.equals("RIGHTPAR")) rightBit = true;
				if (e.equals("SEMICOLON")) semiBit = true;
				if (e.equals("ID")) idBit = true;
				if (e.equals("ASSIGN")) assignBit = true;
				if (e.equals("READ")) readBit = true;
				if (e.equals("COMMA")) commaBit = true;
				if (e.equals("INTNUM")) intnumBit = true;
				if (e.equals("PLUS")) plusBit = true;
				if (e.equals("MINUS")) minusBit = true;
				if (e.equals("MULTIPLY")) multiplyBit = true;
				if (e.equals("MODULO")) moduloBit = true;
			}
			this.inputFile = inputFile;
			reader = new BufferedReader(new FileReader(inputFile));
			inputString = "";
			
			while (true) {
				String readString = reader.readLine();
				if (readString == null) break;
				inputString += readString + " ";
			}
			
		} catch (FileNotFoundException e) {
			System.err.println("Could not find the file with the string to be parsed");
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public void retrieveTokens() {
		String tokenizedString = inputString;

		if (idBit) {
			Matcher matcher = PATTERNID.matcher(tokenizedString);
			ArrayList<String> matchedStrings = new ArrayList<String>();
			while (matcher.find()) {
				String matchedString = tokenizedString.substring(matcher.start(), matcher.end());

				if (matchedString.length() > MAX_ID_LENGTH || matchedString.equals("BEGIN") || matchedString.equals("END") || matchedString.equals("PRINT") || matchedString.equals("READ")) continue;
				else {
					matchedStrings.add(matchedString);
				}
			}
			for (String e: matchedStrings) tokenizedString = tokenizedString.replace(e, "ID");
		}

		if (leftBit) tokenizedString = tokenizedString.replace("(", " LEFTPAR ");
		if (rightBit) tokenizedString = tokenizedString.replace(")", " RIGHTPAR ");
		if (multiplyBit) tokenizedString = tokenizedString.replace("*", " MULTIPLY ");
		if (plusBit) tokenizedString = tokenizedString.replace("+", " PLUS " );
		if (minusBit) tokenizedString = tokenizedString.replace("-", " MINUS ");
		if (moduloBit) tokenizedString = tokenizedString.replace("%", " MODULO ");
		if (semiBit) tokenizedString = tokenizedString.replace(";", " SEMICOLON ");
		if (assignBit) tokenizedString = tokenizedString.replace(":=", " ASSIGN ");
		if (commaBit) tokenizedString = tokenizedString.replace(",", " COMMA ");

		if (intnumBit) {
			Matcher matcherNum = PATTERNNUM.matcher(tokenizedString);
			tokenizedString = matcherNum.replaceAll("INTNUM");
		}

		tokenizedString = tokenizedString.replaceAll("  ", " ").trim();
		tokens = tokenizedString.split(" ");

		boolean check = true;
		
		//FIXME
		for (String e: tokens) {
			if (!(e.equals("BEGIN") || e.equals("END") || e.equals("PRINT") || e.equals("LEFTPAR") || e.equals("RIGHTPAR")
					|| e.equals("SEMICOLON") || e.equals("ID") || e.equals("ASSIGN") || e.equals("READ") 
					|| e.equals("COMMA") || e.equals("INTNUM") || e.equals("PLUS") || e.equals("MINUS") || e.equals("MULTIPLY")
					|| e.equals("MODULO"))) {
				check = false;
			}
		}
		if (!check) tokens = null;
	}

	public String[] getTokens() {
		return tokens;
	}

	/**
	 * To close the input reader after scanning
	 */ 
	public void close() {
		try {
			reader.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public BufferedReader getReader() {
		return reader;
	}

	public void setReader(BufferedReader reader) {
		this.reader = reader;
	}

	public File getInputFile() {
		return inputFile;
	}

	public void setInputFile(File inputFile) {
		this.inputFile = inputFile;
	}

	public void setTokens(String[] tokens) {
		this.tokens = tokens;
	}




}
